
#ifndef __LIBERTY_LIBRARY_ASSETFOLDER_H__
#define __LIBERTY_LIBRARY_ASSETFOLDER_H__

#include <Liberty3D/Liberty3D.h>
#include <Liberty3D/Engine/Uuid.h>
#include <Liberty3D/Engine/AssetFileFolder.h>
#include <Liberty3D/Engine/Path.h>
#include <Liberty3D/Engine/ISerializer.h>
#include <Liberty3D/Library/Mutex/Local.h>

namespace Liberty { namespace Library {
    class IAssetFolder {
    public:
        virtual ~IAssetFolder() {}

    public:
        virtual ISharedLock* __folderLockShared() = 0;
        virtual void __folderSetStatus(ObjectStatus) = 0;
        virtual void __folderSetUuid(const Liberty::Engine::Uuid& uuid) = 0;
    };

    template <typename BaseAssetImporter>
    class AssetFolder : public BaseAssetImporter, public IAssetFolder {
    protected:
        std::shared_ptr<AssetDepotFolder> _depot;
        Liberty::Engine::Uuid             _uuid;
        ObjectStatus                      _status;

    public:
        AssetFolder(const std::shared_ptr<AssetDepotFolder>& depot) :
            _depot (depot),
            _status(ModifiedInDepot)
        {
            this->_mutex = std::shared_ptr<ISharedMutex>(new Liberty::Library::Mutex::Impl::Local::SharedMutex());
        }

    public:
        virtual std::shared_ptr<IAssetDepot> assetDepot() const {
            return _depot;
        }

        virtual ObjectStatus assetStatus() const {
            typename BaseAssetImporter::SharedLock lock(this);

            return _status;
        }

        virtual Liberty::Engine::Uuid assetUuid() const {
            return _uuid;
        }

        virtual std::string assetPath() const {
            return _depot->pathForUuid(_uuid);
        }

        virtual std::string assetPath(const Liberty::Engine::Uuid& uuid) const {
            return _depot->pathForUuid(uuid);
        }

        virtual std::string assetRelative(const std::string& otherPath, Liberty::Engine::Uuid* uuid = nullptr) const {
            std::string rel(Liberty::Engine::Path::relativeTo(_depot->pathForUuid(_uuid), otherPath));

            if (uuid) {
                *uuid = _depot->uuidForPath(rel);
            }

            return rel;
        }

        virtual void serializeObject(Liberty::Engine::ISerializer* s) {
            s->serialize("uuid", _uuid);
            BaseAssetImporter::serializeObject(s);
        }

    public:
        virtual void mappedObjectLoad() {
            throw new std::runtime_error("TODO");
        }

        virtual void mappedObjectSave() const {
            throw new std::runtime_error("TODO");
        }

        virtual bool mappedObjectNeedsReload() const {
            return _status == ModifiedInDepot;
        }

    public:
        virtual ISharedLock* __folderLockShared() {
            return this->_mutex->lockShared();
        }

        virtual void __folderSetStatus(ObjectStatus status) {
            _status = status;
        }

        virtual void __folderSetUuid(const Liberty::Engine::Uuid& uuid) {
            _uuid = uuid;
        }
    };
}}

#endif
